﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Automation;
using System.Collections;
using Tedds_Tool.Automatables;
using CommonInterfaces.Models;
using Compiled_Tests;
using Compiled_Tests.Utils;
using LEET.LEETCommon.WidgetLookup;
using System.Windows;
using LEET.LEETCommon.AutomationAbstractions;

namespace Tedds_Tool
{
    public class ElementState : IElementState
    {
        #region Attributes

        /// <summary>
        /// Root GUI element of process
        /// </summary>
        private AutomationElement root;
        IDictionary<String, IDictionary<String, String>> cache;
        IList<ILEETHackModule> hacks;

        /// <summary>
        /// Stores full hierarchy path for referencing of elements from its root
        /// </summary>
        private List<string> path;
        public List<string> fullPath { get { return path; } }

        /// <summary>
        /// Stores element's bounding rectangle for highlighter box referencing
        /// </summary>
        private List<Rect> location;
        public List<Rect> elementLocation { get { return location; } private set { elementLocation = location; } }

        #endregion

        public ElementState(IBox box, IList<ILEETHackModule> hacks) : this(box.RootElement, hacks) { }

        public ElementState(AutomationElement ae, IList<ILEETHackModule> hacks)
        {
            this.hacks = hacks;
            this.root = ae;
            cache = new Dictionary<String, IDictionary<String, String>>();
            if (ae != null)
                cacheElements();
        }

        public ElementState()
        {
            path = new List<string>();
            location = new List<Rect>();
            cache = new Dictionary<String, IDictionary<String, String>>();
        }

        public IEnumerable<string> Property(string elem)
        {
            try
            {
                int index = cache.Keys.ToList().IndexOf(elem);
                if (index != -1)
                    return cache.Values.ElementAt(index).Keys;
                else
                    return new List<String>();
            }
            catch { return new List<String>(); }
        }

        public string ValueOf(string elem, string prop)
        {
            IDictionary<String, String> props = null;
            cache.TryGetValue(elem, out props);
            if (props != null)
            {
                String ret = null;
                props.TryGetValue(prop, out ret);
                if (ret != null)
                    return ret;
            }
            return "";
        }

        public int IndexOf(string elem)
        {
            return cache.Keys.ToList().IndexOf(elem);
        }

        public IEnumerable<string> Elements
        {
            get
            {
                return cache.Keys;
            }
        }

        private void cacheElements()
        {
            if (root == null)
                return;
            
            HierarchyFinder.SetUIAHierarchy(root);
            List<AutomationElement> autCache = HierarchyFinder.aes;
            location = HierarchyFinder.locations;
            path = HierarchyFinder.fullpaths.ToList();
            
            HierarchyFinder.AddPatterns(hacks);
            Dictionary<AutomationElement, Dictionary<string, string>> props  = HierarchyFinder.allProperties;

            if (autCache != null)
                foreach (KeyValuePair<AutomationElement, Dictionary<string, string>> current in props)
                {
                    if(!current.Key.Cached.IsOffscreen)
                        cache.Add((current.Key.Cached.AutomationId == "" ? current.Key.Cached.Name + "_" + cache.Count : current.Key.Cached.AutomationId + "_" + cache.Count), current.Value);
                }
        }

        public Rect GetAELocation(string elem)
        {
            int index = cache.Keys.ToList().IndexOf(elem);
            return location[index];
        }
    }
}
